package de.tayrracer.geoobjects;

import java.awt.Color;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;

public class Mesh extends BaseObject {
	private ArrayList<Triangle> theMesh = new ArrayList<Triangle>();
	private Triangle[] theBoundingBox = new Triangle[8];
	
	public Mesh (String filename, double[] position)
	{
		this.position = position;
		FileReader fr = null;
		try {
			fr = new FileReader(filename);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	    BufferedReader br = new BufferedReader(fr);

	    String line = "";
	    ArrayList<double[]> vertices = new ArrayList<double[]>();
		try {
			line = br.readLine();
			while(line != null){
				//Vertex
				if(line.startsWith("v ")){
					String[] coordinates = line.split(" ");
					double[] vertex = new double[3];
					vertex[0] = Double.parseDouble(coordinates[1])+this.position[0];
					vertex[1] = Double.parseDouble(coordinates[2])+this.position[1];
					vertex[2] = Double.parseDouble(coordinates[3])+this.position[2];
					vertices.add(vertex);
				}else if(line.startsWith("f ")){
					String[] faceparts = line.split(" ");
					if(faceparts.length > 4){
						String tempString = faceparts[1];
						tempString = (faceparts[1].indexOf("/")>-1)?faceparts[1].substring(0, faceparts[1].indexOf("/")):faceparts[1];
						double[] v1 = vertices.get(Integer.parseInt(tempString)-1);
						tempString = (faceparts[2].indexOf("/")>-1)?faceparts[2].substring(0, faceparts[2].indexOf("/")):faceparts[2];
						double[] v2 = vertices.get(Integer.parseInt(tempString)-1);
						tempString = (faceparts[3].indexOf("/")>-1)?faceparts[3].substring(0, faceparts[3].indexOf("/")):faceparts[3];
						double[] v3 = vertices.get(Integer.parseInt(tempString)-1);
						tempString = (faceparts[4].indexOf("/")>-1)?faceparts[4].substring(0, faceparts[4].indexOf("/")):faceparts[4];
						double[] v4 = vertices.get(Integer.parseInt(tempString)-1);
						
						Triangle tempTri = new Triangle(v1,v2,v3);
						tempTri.objectColor = Color.GREEN;
						theMesh.add(tempTri);
						tempTri = new Triangle(v1,v3,v4);
						tempTri.objectColor = Color.GREEN;
						theMesh.add(tempTri);
					}else{
						String tempString = faceparts[1];
						tempString = (faceparts[1].indexOf("/")>-1)?faceparts[1].substring(0, faceparts[1].indexOf("/")):faceparts[1];
						double[] v1 = vertices.get(Integer.parseInt(tempString)-1);
						tempString = (faceparts[2].indexOf("/")>-1)?faceparts[2].substring(0, faceparts[2].indexOf("/")):faceparts[2];
						double[] v2 = vertices.get(Integer.parseInt(tempString)-1);
						tempString = (faceparts[3].indexOf("/")>-1)?faceparts[3].substring(0, faceparts[3].indexOf("/")):faceparts[3];
						double[] v3 = vertices.get(Integer.parseInt(tempString)-1);
						
						Triangle tempTri = new Triangle(v1,v2,v3);
						tempTri.objectColor = Color.GREEN;
						theMesh.add(tempTri);
					}
				}		
				
				line = br.readLine();
			}
			br.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		double[] vbb1 = new double[]{Double.POSITIVE_INFINITY,Double.POSITIVE_INFINITY,Double.POSITIVE_INFINITY};
		double[] vbb2 = new double[]{Double.NEGATIVE_INFINITY,Double.NEGATIVE_INFINITY,Double.NEGATIVE_INFINITY};
		for(double[] v: vertices){
			if(v[0] < vbb1[0]) vbb1[0]=v[0];
			if(v[1] < vbb1[1]) vbb1[1]=v[1];
			if(v[2] < vbb1[2]) vbb1[2]=v[2];
			if(v[0] > vbb2[0]) vbb2[0]=v[0];
			if(v[1] > vbb2[1]) vbb2[1]=v[1];
			if(v[2] > vbb2[2]) vbb2[2]=v[2];
		}
		theBoundingBox[0] = new Triangle(vbb1,new double[]{vbb2[0],vbb1[1],vbb1[2]},new double[]{vbb2[0],vbb2[1],vbb1[2]});
		theBoundingBox[1] = new Triangle(vbb1,new double[]{vbb1[0],vbb2[1],vbb1[2]},new double[]{vbb2[0],vbb2[1],vbb1[2]});
		theBoundingBox[2] = new Triangle(vbb2,new double[]{vbb1[0],vbb2[1],vbb2[2]},new double[]{vbb1[0],vbb1[1],vbb2[2]});
		theBoundingBox[3] = new Triangle(vbb2,new double[]{vbb2[0],vbb1[1],vbb2[2]},new double[]{vbb1[0],vbb1[1],vbb2[2]});
		theBoundingBox[4] = new Triangle(vbb1,new double[]{vbb1[0],vbb1[1],vbb2[2]},new double[]{vbb1[0],vbb2[1],vbb2[2]});
		theBoundingBox[5] = new Triangle(vbb1,new double[]{vbb1[0],vbb2[1],vbb1[2]},new double[]{vbb1[0],vbb2[1],vbb2[2]});
		theBoundingBox[6] = new Triangle(vbb2,new double[]{vbb2[0],vbb1[1],vbb2[2]},new double[]{vbb2[0],vbb1[1],vbb1[2]});
		theBoundingBox[7] = new Triangle(vbb2,new double[]{vbb2[0],vbb2[1],vbb1[2]},new double[]{vbb2[0],vbb1[1],vbb1[2]});
	}
	
	private double[] isBoundingBoxCut(double[] origin, double[] direction){
		for(Triangle t: theBoundingBox)
			if(t.getColorForCut(origin, direction, new BaseObject[]{}, 0) != null)
				return new double[]{};
		return null;
	}
	
	public Ray getColorForCut(double[] origin, double[] direction, BaseObject[] objects, int count){
		if(isBoundingBoxCut(origin,direction)!=null && count > 0){
			Ray result = null;
			Ray cutRay = null;
			double tempDist = Double.POSITIVE_INFINITY;
			double ttDist = 0;
			for(Triangle t: theMesh){
				cutRay = t.getColorForCut(origin, direction, objects, count-1);
				if(cutRay != null){
					ttDist = de.tayrracer.Math.distance(cutRay.position, origin);
					if(ttDist<tempDist){
						tempDist = ttDist;
						result = cutRay;
					}
				}
			}
			return result;
		}
		return null;
	}
}
